package controllers;

import db.DriverDAO;
import db.EventDAO;
import db.ServiceDAO;
import db.VehicleDAO;
import db.VehicleTypeDAO;
import java.util.ArrayList;
import java.sql.Date;
import java.util.List;
import java.sql.Time;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class Event {

    private int id;
    private Service service;
    private int serviceID;
    private Driver driver;
    private int driverID;
    private Vehicle vehicle;
    private int vehicleID;
    private String notes;
    private ArrayList<Driver> possibleDrivers;
    private ArrayList<Vehicle> possibleVehicles;
    private Date date;
    private Time servStart;
    private Time servEnd;
    private int defaultDriverID;
    private GregorianCalendar dateCal;

    public Event() {
    }

    public Event(int serviceID) {
        this.serviceID = serviceID;

        this.service = ServiceDAO.getServiceByID(serviceID);
        servStart = new Time(service.getStartTime().getTime() - (service.getDriveTime() * 60 * 1000));
        servEnd = new Time(service.getEndTime().getTime() + (service.getDriveTime() * 60 * 1000));
    }

    public Event(int id, int serviceID, int driverID, int vehicleID, String notes, Date date, int defaultDriverID) {
        this.id = id;
        this.serviceID = serviceID;
        this.driverID = driverID;
        this.vehicleID = vehicleID;
        this.notes = notes;
        this.date = date;
        this.defaultDriverID = defaultDriverID;

        this.service = ServiceDAO.getServiceByID(serviceID);
        this.driver = DriverDAO.getDriverByID(driverID);
        this.vehicle = VehicleDAO.getVehicleByID(vehicleID);

        dateCal = new GregorianCalendar();
        dateCal.set(Calendar.LONG, (int)date.getTime());
        
        service.setDay(ExtMethods.getDayByNumFull(dateCal.get(Calendar.DAY_OF_WEEK)));

        servStart = new Time(service.getStartTime().getTime() - (service.getDriveTime() * 60 * 1000));
        servEnd = new Time(service.getEndTime().getTime() + (service.getDriveTime() * 60 * 1000));
    }

    public int getId() {
        return id;
    }

    public Service getService() {
        return service;
    }

    public void setService(Service service) {
        this.service = service;
    }

    public Driver getDriver() {
        return driver;
    }

    public void setDriver(Driver driver) {
        this.driver = driver;
    }

    public Vehicle getVehicle() {
        return vehicle;
    }

    public void setVehicle(Vehicle vehicle) {
        this.vehicle = vehicle;
    }

    public String getNotes() {
        return notes;
    }

    public void setNotes(String notes) {
        this.notes = notes;
    }

    public int getDriverID() {
        return driverID;
    }

    public void setDriverID(int driverID) {
        this.driverID = driverID;
    }

    public int getServiceID() {
        return serviceID;
    }

    public void setServiceID(int serviceID) {
        this.serviceID = serviceID;
    }

    public int getVehicleID() {
        return vehicleID;
    }

    public void setVehicleID(int vehicleID) {
        this.vehicleID = vehicleID;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public int getDefaultDriverID() {
        return defaultDriverID;
    }

    public void setDefaultDriverID(int defaultDriverID) {
        this.defaultDriverID = defaultDriverID;
    }

    public List<Event> getEvents() {
        return EventDAO.getEvents();
    }

    public List<Driver> getPossibleDrivers() {
        possibleDrivers = new ArrayList<Driver>();
        List<Driver> drivers = DriverDAO.getDrivers();

        for (Driver d : drivers) {

            for (TimeSlot ts : d.getTimeSlotsForDay(dateCal.get(Calendar.DAY_OF_WEEK))) {
                if ((ts.getStartTime().before(servStart) || ts.getStartTime().equals(servStart))
                        && (ts.getEndTime().after(servEnd) ||  ts.getEndTime().equals(servEnd))
                        && ts.getWeekday().equals(getService().getDay())){
                    possibleDrivers.add(d);
                    break;
                }
            }
        }
        return possibleDrivers;
    }

    public List<Driver> getPossibleDrivers(ArrayList<TimeSlot> takenSlots, ArrayList<Driver> drivers) {
        possibleDrivers = new ArrayList<Driver>();
        boolean canDrive = false;
        if (getService().getTransnumb() <= 10) {
            for (Driver d : drivers) {

                for (TimeSlot ts : d.getTimeSlots()) {
                    if ((ts.getStartTime().before(servStart) || ts.getStartTime().equals(servStart))
                        && (ts.getEndTime().after(servEnd) ||  ts.getEndTime().equals(servEnd))
                        && ts.getWeekday().equals(getService().getDay())){

                        canDrive = true;
                        for (TimeSlot takenTS : takenSlots) {

                            if (takenTS.getDriverID() == d.getId()) {

                                boolean startBefServStart;
                                boolean startAftServEnd;
                                boolean endBefServStart;
                                boolean endAftServEnd;


                                startBefServStart = takenTS.getStartTime().before(servStart);
                                startAftServEnd = takenTS.getStartTime().after(servEnd);
                                endBefServStart = takenTS.getEndTime().before(servStart);
                                endAftServEnd = takenTS.getEndTime().after(servEnd);

                                if (!((startBefServStart && endBefServStart)
                                        || (startAftServEnd && endAftServEnd))) {
                                    canDrive = false;
                                    break;
                                }
                            }
                        }
                    }
                    if (!canDrive) {
                        possibleDrivers.add(d);
                        break;
                    }
                }
            }
        }
        return possibleDrivers;
    }

    public List<Vehicle> getPossibleVehicles(ArrayList<TimeSlot> takenSlots, ArrayList<Vehicle> Vehicles) {

        possibleVehicles = new ArrayList<Vehicle>();
        boolean canDrive = false;
        for (Vehicle v : Vehicles) {
            for (VehicleType vt : VehicleTypeDAO.getVehicleTypes()) {
                if (vt.getNumOfSeats() > service.getTransnumb() && !vt.isIgnoreGenerate()) {
                    canDrive = true;
                    if (v.getVehicleTypeID() == vt.getId()) {
                        for (TimeSlot takenTS : takenSlots) {

                            if (takenTS.getDriverID() == v.getId()) {  //Hacked up, DriverID is really VehicleID

                                boolean startBefServStart;
                                boolean startAftServEnd;
                                boolean endBefServStart;
                                boolean endAftServEnd;
                                
                                startBefServStart = takenTS.getStartTime().before(servStart);
                                startAftServEnd = takenTS.getStartTime().after(servEnd);
                                endBefServStart = takenTS.getEndTime().before(servStart);
                                endAftServEnd = takenTS.getEndTime().after(servEnd);

                                if (!((startBefServStart && endBefServStart)
                                        || (startAftServEnd && endAftServEnd))) {
                                    canDrive = false;
                                    break;
                                }
                            }
                        }
                        if (canDrive) {
                            possibleVehicles.add(v);
                            break;
                        }
                    }
                    if (possibleVehicles.size() > 0) {
                        break;
                    }
                }
            }
        }
        return possibleVehicles;
    }
}
